use redis::AsyncCommands;

use crate::{error::AppError, Result};

/// 获取redis异步连接
async fn get_conn(rdc: &redis::Client) -> Result<redis::aio::Connection> {
    let c = rdc.get_async_connection().await.map_err(AppError::from)?;
    Ok(c)
}

/// 设置值到redis
pub(crate) async fn set(
    rdc: &redis::Client,
    key: &str,
    value: &impl serde::Serialize,
    secs: usize,
) -> Result<()> {
    let mut conn = get_conn(rdc).await?;
    let value = serde_json::json!(value).to_string();
    conn.set_ex(key, value, secs)
        .await
        .map_err(AppError::from)?;
    Ok(())
}

/// 从redis读取值
pub(crate) async fn get<T: serde::de::DeserializeOwned>(
    rdc: &redis::Client,
    key: &str,
) -> Result<Option<T>> {
    let mut conn = get_conn(rdc).await?;
    let value: Option<String> = conn.get(key).await.map_err(AppError::from)?;
    let data: Option<T> = match value {
        Some(s) => serde_json::from_str(s.as_ref()).map_err(AppError::from)?,
        None => None,
    };
    Ok(data)
}
